// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h

#ifndef __S_KEY_MAP_H_INCLUDED__
#define __S_KEY_MAP_H_INCLUDED__

#include "IrrCompileConfig.h"

#include "Keycodes.h"

namespace irr
{

	//! enumeration for key actions. Used for example in the FPS Camera.
	enum EKEY_ACTION
	{
		EKA_MOVE_FORWARD = 0,
		EKA_MOVE_BACKWARD,
		EKA_STRAFE_LEFT,
		EKA_STRAFE_RIGHT,
		EKA_JUMP_UP,
		EKA_CROUCH,

#ifdef DELPHI_WRAP
		EKA_NONE,
#endif
		EKA_COUNT,
		//! This value is not used. It only forces this enumeration to compile in 32 bit.
		EKA_FORCE_32BIT = 0x7fffffff
	};

	//! Struct storing which key belongs to which action.
	struct SKeyMap
	{
		SKeyMap() 
		{
#ifdef DELPHI_WRAP
			Action = EKA_NONE;
			KeyCode = KEY_HELP;
#endif
		}
		SKeyMap(EKEY_ACTION action, EKEY_CODE keyCode) : Action(action), KeyCode(keyCode) {}

		EKEY_ACTION Action;
		EKEY_CODE KeyCode;
	};

#ifdef DELPHI_WRAP
	static SKeyMap noneKey = SKeyMap();

	class KeyMaps
	{
	private:
		SKeyMap * keyMap;
		u32 mapCount;
		u32 capacityCount;
	private:
		void Grow()
		{
			u32 delta = 16;

			SetCapacity(capacityCount + delta);
		}

		void SetCapacity(u32 NewCapacity)
		{
			if (NewCapacity > capacityCount)
			{
				SKeyMap *newKeyMap = new SKeyMap[NewCapacity];
				
				if (keyMap != 0)
				{
					for (u32 i = 0; i < mapCount; i++)
					{
						newKeyMap[i] = keyMap[i];
					}
					delete[] keyMap;
				}
				keyMap = newKeyMap;
				capacityCount = NewCapacity;
			}
		}
	public:
		KeyMaps()
		{
			mapCount = 0;
			capacityCount = 8;
			keyMap = new SKeyMap[capacityCount];
		}
		
		~KeyMaps()
		{
			delete[] keyMap;
		}
	public:
		u32 size() const
		{
			return mapCount;
		}

		SKeyMap& operator [](u32 index) const
		{
			if (index < mapCount)
			{
				return keyMap[index];
			}
			else
			{
				return noneKey;
			}
		}

	public:
		virtual u32 _STDCALL_ AddKeyMap(const SKeyMap & map)
		{
			if (mapCount == capacityCount)
				Grow();
			keyMap[mapCount] = map;
			mapCount++;

			return mapCount - 1;			
		}

		virtual void _STDCALL_ ClearKeyMap()
		{
			mapCount = 0;
		}

		virtual const SKeyMap & _STDCALL_ GetKeyMap(const u32 Index) const
		{
			return (*this)[Index];
		}

		virtual u32 _STDCALL_ GetCount() const
		{
			return mapCount;
		}

		virtual void _STDCALL_ Clone(const KeyMaps &Other)
		{
			if (keyMap != 0)
				delete[] keyMap;

			capacityCount = Other.mapCount;
			mapCount = Other.mapCount;
			
			keyMap = new SKeyMap[capacityCount];

			for (u32 i=0; i<mapCount; i++)
			{
				keyMap[i] = Other.keyMap[i];
			}
		}
	};

#endif

} // end namespace irr

#endif

